#include <myprintf.h>
#include "cmsis_os2.h"
#include "debug.h"
#include "usart.h"
#include "cJSON.h"

USART3_RECEIVETYPE Usart3_Type =  { 0, { 0 } };
USART3_RECEIVETYPE usart3_rx = { 0, { 0 } };
extern osMessageQueueId_t myQueue03Handle;
para para_st;
const char *para_type_name[] =
{
		"node",
		"trans",
};
const char *para_node_name[PARA_ELE_NUM] =
{
		"node_num",
		"node_name",
		"productKey",
		"deviceName",
		"deviceSecret",
};
void USART3_RxIdleCallback(UART_HandleTypeDef *huart)
{
	if ((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET)) {
		__HAL_UART_CLEAR_IDLEFLAG(huart);
		HAL_UART_DMAStop(huart);
		Usart3_Type.RX_Size = USART3_LEN - huart->hdmarx->Instance->NDTR;
		/************************************************************************************/
		if (Usart3_Type.RX_Size <= USART3_LEN)
			osMessageQueuePut(myQueue03Handle, &Usart3_Type, 0U, 0U);
		//		HAL_UART_Transmit(&huart3, &Usart3_Type.RX_pData[0], Usart3_Type.RX_Size, 0xFFFF);
		memset(&Usart3_Type.RX_pData, 0x00, Usart3_Type.RX_Size);
		/************************************************************************************/
		__HAL_UART_CLEAR_OREFLAG(huart);
		HAL_UART_Receive_DMA(huart, &Usart3_Type.RX_pData[0], USART3_LEN);
	}
}

#if 0
void para_initial(void)
{
}

#define MASTER_ASK		0xAA
#define SLAVE_SEND		0x55
#define MASTER_ACK		0xFF

#define ORDER_READ		0xAA
#define ORDER_WRITE		0x55
#define WAY_DISCRETE	0xAA
#define WAY_CONTINUOUS	0x55

#define ACK_READ_DIS	0x01
#define ACK_READ_CON	0x02
#define ACK_WRITE_DIS	0x03
#define ACK_WRITE_CON	0x04

#define REG_NUM			32
typedef struct {
	uint16_t dev_addr;
	uint16_t reg_buff[REG_NUM];
}protocol;
protocol protocol_st;

#define TX_BUFF_LEN		128
typedef struct {
	uint8_t head;
	uint16_t addr;
	uint8_t order;
	uint8_t way;

	uint8_t reg_start;
	uint8_t reg_len;

	uint16_t crc;
	uint8_t txbuff[TX_BUFF_LEN];

	uint8_t ack_value;
}rx_deal;
rx_deal rx_deal_st;
static void read_deal(uint8_t *value, uint16_t len);
static void write_deal(uint8_t *value, uint16_t len);

#define CRC_DIR_RX (0x01)
#define CRC_DIR_TX (0x00)
uint16_t crc_check(uint8_t dir, uint8_t *Rxbuff, uint32_t Rx_len, uint16_t *crc)
{
	uint16_t temp = 0;
	uint32_t len = Rx_len - 2; //
	uint16_t crc_result = 0xffff;
	uint16_t crc_num = 0; //
	int xor_flag = 0;     //
	if (Rx_len <= 2)
		return HAL_ERROR;
	for (int i = 0; i < len; i++) {
		crc_result ^= Rxbuff[i];
		crc_num = (crc_result & 0x0001);
		for (int m = 0; m < 8; m++) {
			if (crc_num == 1)
				xor_flag = 1;
			else
				xor_flag = 0;
			crc_result >>= 1;
			if (xor_flag)
				crc_result ^= 0xa001;
			crc_num = (crc_result & 0x0001);
		}
	}
	if (dir == CRC_DIR_RX) {
		temp = (uint16_t) Rxbuff[Rx_len - 1] << 8 | Rxbuff[Rx_len - 2];
		if (crc_result == temp) {
			return HAL_OK;
		} else
			return HAL_ERROR;
	} else if (dir == CRC_DIR_TX) {
		*crc = crc_result;
		return HAL_OK;
	}
}


void usart3_rx_deal(USART3_RECEIVETYPE *usart3_rx) {
	//	HAL_UART_Transmit(&huart3, &usart3_rx->RX_pData[0], usart3_rx->RX_Size, 0xFFFF);

	uint8_t *ptr = NULL;
	uint16_t len = 0;
	ptr = &usart3_rx->RX_pData[0];
	len = usart3_rx->RX_Size;

	rx_deal_st.head = 0;
	rx_deal_st.addr = 0;
	rx_deal_st.order = 0;
	rx_deal_st.way = 0;
	rx_deal_st.reg_start = 0;
	rx_deal_st.reg_len = 0;
	rx_deal_st.crc = 0;

	if(crc_check(CRC_DIR_RX, ptr, len, &rx_deal_st.crc) != HAL_OK) {
		DEBUG_E("CRC error\r\n");
		return;
	}

	rx_deal_st.head = *ptr;
	DEBUG_L("HEAD 0x%x \r\n",rx_deal_st.head);
	if((rx_deal_st.head != MASTER_ASK)&&(rx_deal_st.head != MASTER_ACK)) {
		return;
	}

	/**************************************************************/
	protocol_st.dev_addr = 0x0103;
	/**************************************************************/
	rx_deal_st.addr = (*(ptr+1)) << 8;
	rx_deal_st.addr |= (*(ptr+2));
	DEBUG_L("ADDR 0x%x \r\n",rx_deal_st.addr);
	if(rx_deal_st.addr != protocol_st.dev_addr)
		return;

	rx_deal_st.order = (*(ptr+3));
	DEBUG_L("ORDER 0x%x \r\n",rx_deal_st.order);
	if((rx_deal_st.order != ORDER_READ)&&(rx_deal_st.order != ORDER_WRITE)) {
		return;
	}

	rx_deal_st.way = (*(ptr+4));
	DEBUG_L("WAY 0x%x \r\n",rx_deal_st.way);
	if((rx_deal_st.way != WAY_DISCRETE)&&(rx_deal_st.way != WAY_CONTINUOUS)) {
		return;
	}

	if(rx_deal_st.head == MASTER_ASK) {
		rx_deal_st.txbuff[0] = SLAVE_SEND;
		rx_deal_st.txbuff[1] = rx_deal_st.addr >> 8;
		rx_deal_st.txbuff[2] = rx_deal_st.addr;
		rx_deal_st.txbuff[3] = rx_deal_st.order;
		rx_deal_st.txbuff[4] = rx_deal_st.way;

		if(rx_deal_st.order == ORDER_READ) {
			read_deal(ptr,len);
		}else if(rx_deal_st.order == ORDER_WRITE) {
			write_deal(ptr,len);
		}
	}
	if(rx_deal_st.head == MASTER_ACK) {
		if(len > 7)
			return;
		rx_deal_st.ack_value = 0;
		if(rx_deal_st.order == ORDER_READ) {
			if(rx_deal_st.way == WAY_DISCRETE)
				rx_deal_st.ack_value = ACK_READ_DIS;
			else if(rx_deal_st.way == WAY_CONTINUOUS)
				rx_deal_st.ack_value = ACK_READ_CON;
		}
		if(rx_deal_st.order == ORDER_WRITE) {
			if(rx_deal_st.way == WAY_DISCRETE)
				rx_deal_st.ack_value = ACK_WRITE_DIS;
			else if(rx_deal_st.way == WAY_CONTINUOUS)
				rx_deal_st.ack_value = ACK_WRITE_CON;
		}
		HAL_UART_Transmit(&huart3, &rx_deal_st.ack_value, 1, 0xFFFF);
	}
}
void read_deal(uint8_t *value, uint16_t len) {
	uint8_t *ptr = NULL;
	ptr = value;

	switch(rx_deal_st.way) {
		case WAY_DISCRETE:
			for(uint8_t i = 0; i < len - 7; i++) {
				if((*(ptr+5+i)) < REG_NUM) {
					rx_deal_st.txbuff[5+i*3] = (*(ptr+5+i));
					rx_deal_st.txbuff[5+i*3+1] = protocol_st.reg_buff[(*(ptr+5+i))] >> 8;
					rx_deal_st.txbuff[5+i*3+2] = protocol_st.reg_buff[(*(ptr+5+i))];
				}
			}
			crc_check(CRC_DIR_TX, &rx_deal_st.txbuff, (len - 7)*2 + len, &rx_deal_st.crc);
			rx_deal_st.txbuff[(len - 7)*2 + len - 2] = rx_deal_st.crc;
			rx_deal_st.txbuff[(len - 7)*2 + len - 1] = rx_deal_st.crc >> 8;
			HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], (len - 7)*2 + len, 0xFFFF);
		break;
		case WAY_CONTINUOUS:
			rx_deal_st.reg_start = (*(ptr+5));
			rx_deal_st.reg_len = (*(ptr+6));
			rx_deal_st.txbuff[5] = rx_deal_st.reg_start;
			rx_deal_st.txbuff[6] = rx_deal_st.reg_len;
			if(rx_deal_st.reg_len > REG_NUM ) {
				rx_deal_st.reg_len = REG_NUM;
			}
			for(uint8_t k = 0; k < rx_deal_st.reg_len; k++) {
				rx_deal_st.txbuff[7+k*2] = protocol_st.reg_buff[rx_deal_st.reg_start+k]>>8;
				rx_deal_st.txbuff[7+k*2+1] = protocol_st.reg_buff[rx_deal_st.reg_start+k];
			}
			crc_check(CRC_DIR_TX, &rx_deal_st.txbuff, rx_deal_st.reg_len*2 + len, &rx_deal_st.crc);
			rx_deal_st.txbuff[rx_deal_st.reg_len*2 + len - 2] = rx_deal_st.crc;
			rx_deal_st.txbuff[rx_deal_st.reg_len*2 + len - 1] = rx_deal_st.crc >> 8;
			HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], rx_deal_st.reg_len*2 + len, 0xFFFF);
		break;
	}
}
void write_deal(uint8_t *value, uint16_t len) {
	uint8_t *ptr = NULL;
	ptr = value;

	switch(rx_deal_st.way) {
		case WAY_DISCRETE:
			for(uint8_t i = 0; i < (len - 7) / 3; i++)
			{
				if((*(ptr+5+i*3)) < REG_NUM){
					protocol_st.reg_buff[(*(ptr+5+i*3))] = (*(ptr+5+i*3+1))<<8;
					protocol_st.reg_buff[(*(ptr+5+i*3))] |= (*(ptr+5+i*3+2));
				}
				rx_deal_st.txbuff[5+i] = (*(ptr+5+i*3));
			}
			crc_check(CRC_DIR_TX, &rx_deal_st.txbuff,(len - 7)/3 + 7, &rx_deal_st.crc);
			rx_deal_st.txbuff[(len - 7)/3 + 7 - 2] = rx_deal_st.crc;
			rx_deal_st.txbuff[(len - 7)/3 + 7 - 1] = rx_deal_st.crc >> 8;
			HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], (len - 7)/3 + 7, 0xFFFF);
		break;
		case WAY_CONTINUOUS:
			rx_deal_st.reg_start = (*(ptr+5));
			rx_deal_st.reg_len = (*(ptr+6));
			rx_deal_st.txbuff[5] = rx_deal_st.reg_start;
			rx_deal_st.txbuff[6] = rx_deal_st.reg_len;
			if(rx_deal_st.reg_len > REG_NUM ) {
				rx_deal_st.reg_len = REG_NUM;
			}
			for(uint8_t k = 0; k < rx_deal_st.reg_len; k++) {
				protocol_st.reg_buff[rx_deal_st.reg_start+k] = (*(ptr+7+k*2))<<8;
				protocol_st.reg_buff[rx_deal_st.reg_start+k] |= (*(ptr+7+k*2+1));
			}
			crc_check(CRC_DIR_TX, &rx_deal_st.txbuff, 9, &rx_deal_st.crc);
			rx_deal_st.txbuff[9 - 2] = rx_deal_st.crc;
			rx_deal_st.txbuff[9 - 1] = rx_deal_st.crc >> 8;
			HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], 9, 0xFFFF);
		break;
	}
}
#endif
#if 1
void usart3_rx_deal(USART3_RECEIVETYPE *usart3_rx)
{
#if 1
	HAL_UART_Transmit(&huart3, &usart3_rx->RX_pData[0], usart3_rx->RX_Size, 0xFFFF);
#endif
	cJSON *json;
	cJSON *object;
	cJSON *item;
	cJSON *array;
	const char *ptr = NULL;
	ptr = (const char*) &usart3_rx->RX_pData[0];
	json = cJSON_Parse(ptr);			//
	if (json == NULL) {
		DEBUG_E("json fmt error:%s\r\n", cJSON_GetErrorPtr());
		return;
	}
	for(uint8_t i = 0; i < PARA_TYPE; i++) {
		object = cJSON_GetObjectItem(json, para_type_name[i]);
		if (object != NULL) {
			DEBUG_L("%s ---\r\n", para_type_name[i]);
			switch (i) {
				case 0 : {
					uint8_t iCount = cJSON_GetArraySize(object);
					DEBUG_L("iCount:%d\r\n", iCount);
					for(uint8_t j = 0; j < iCount; j++) {
						array = cJSON_GetArrayItem(object, j);
						if(array != NULL) {
							for(uint8_t k = 0; k < PARA_ELE_NUM; k++) {
								item = cJSON_GetObjectItem(array, para_node_name[k]);
								if(item != NULL) {
									switch (k)
									{
										case 0:
											para_st.para_node_st[j].para_element_st.node_num = item->valueint;
											DEBUG_L("%d\r\n", para_st.para_node_st[j].para_element_st.node_num);
											break;
										case 1:
											strcpy(para_st.para_node_st[j].para_element_st.node_name, item->valuestring);
											DEBUG_L("%s\r\n", para_st.para_node_st[j].para_element_st.node_name);
											break;
										case 2:
											strcpy(para_st.para_node_st[j].para_element_st.productKey, item->valuestring);
											DEBUG_L("%s\r\n", para_st.para_node_st[j].para_element_st.productKey);
											break;
										case 3:
											strcpy(para_st.para_node_st[j].para_element_st.deviceName, item->valuestring);
											DEBUG_L("%s\r\n", para_st.para_node_st[j].para_element_st.deviceName);
											break;
										case 4:
											strcpy(para_st.para_node_st[j].para_element_st.deviceSecret, item->valuestring);
											DEBUG_L("%s\r\n", para_st.para_node_st[j].para_element_st.deviceSecret);
											break;
										default :
											break;
									}
								}
							}
						}
					}
				}
				break;
				case 1 : {
				}
				break;
				default :
					break;
			}
		}
	}
	cJSON_Delete(json);
	return;
}
#endif
